<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="js/jquery.min.js"></script>
<script src="js/highcharts.js"></script>
<script src="js/arttpl.js"></script>
<script src="js/tmpl.js"></script>
<script src="../dist/fxtpl.js"></script>
<script src="js/bdtpl.js"></script>
<script src="js/kissy.js"></script>
<script src="js/template.js"></script>
<script src="js/juicer.js"></script>
<script src="js/mustache.js"></script>
<title>前端模板引擎性能测试</title>
<style>
body{ font: 14px/20px Microsoft YaHei, \5b8b\4f53, Arial, Verdana;}
body *{ font-family: Arial, Verdana;}
textarea{ width: 800px; height: 50px; padding: 10px; background: #f1f1f1; border-color: #ddd; font-family:Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal; line-height: 20px; color: #333;}
h1{ font-size: 30px; text-align: center;}
h4{ font-size: 20px; font-weight: bold; background: #f1f1f1; padding: 5px;}
.b{font-weight: bold;}
.main{ width: 1000px; margin: 0 auto;}
</style>
</head>

<body>
<div class="main">
    <h1>前端模板引擎性能测试</h1>
    <h4>综合性能测试（编译+渲染）</h4>
    <p>100条数据*1000次编译+渲染[escape:false, cache:false]</p>
    <p><button onclick="startTest(this,0)">开始测试</button></p>
    <p class="test_log"></p>
    <div id="chart_box0"></div>

    <h4>性能测试（编译）</h4>
    <p>100条数据*1000次编译[escape:false, cache:false]</p>
    <p><button onclick="startTest(this,1)">开始测试</button></p>
    <p class="test_log"></p>
    <div id="chart_box1"></div>

    <h4>性能测试（渲染）</h4>
    <p>100条数据*1000次渲染[escape:false, cache:false]</p>
    <p><button onclick="startTest(this,2)">开始测试</button></p>
    <p class="test_log"></p>
    <div id="chart_box2"></div>
</div>

<!-- fxtpl 的模板 -->
<script id="fxtpl" type="text/tmpl">
<ul>
    {{each $list as $data $index}}
        <li>{{$data.index}}. 用户: {{$data.user}}/ 网站：{{$data.site}}</li>
    {{/each}}
</ul>
</script>
<!-- artTemplate 的模板 -->
<script id="template" type="text/tmpl">
<ul>
    {{ each list as data index}}
        <li>{{data.index}}. 用户: {{data.user}}/ 网站：{{data.site}}</li>
    {{ /each }}
</ul>
</script>
<!-- baidu-template 的模板 -->
<script id="baidu-template" type="text/tmpl">
<ul>
    <% for (var val, i = 0, l = list.length; i < l; i ++) { %>
        <% val = list[i]; %>
        <li><%:=val.index%>. 用户: <%:=val.user%>/ 网站：<%:=val.site%></li>
    <% } %>
</ul>
</script>
<!--kissy 的模板 -->
<script id="kissy" type="text/tmpl">
<ul>
    {{#each list as item index}}
        <li>{{index}}. 用户: {{item.user}}/ 网站：{{item.site}}</li>
    {{/each}}
</ul>
</script>
<!-- tmpl 的模板 -->
<script id="tmpl" type="text/tmpl">
<ul>
    <% for (var val, i = 0, l = list.length; i < l; i ++) { %>
        <% val = list[i]; %>
        <li><%=val.index%>. 用户: <%=val.user%>/ 网站：<%=val.site%></li>
    <% } %>
</ul>
</script>
<!--juicer 的模板 -->
<script id="juicer" type="text/tmpl">
<ul>
    {@each list as val}
        <li>$${val.index}. 用户: $${val.user}/ 网站：$${val.site}</li>
    {@/each}
</ul>
</script>
<!--Mustache 的模板 -->
<script id="Mustache" type="text/tmpl">
<ul>
    {{#list}}
        <li>{{{index}}}. 用户: {{{user}}}/ 网站：{{{site}}}</li>
    {{/list}}
</ul>
</script>

</body>
<script>
// 数据量
var length = 100;
// 渲染次数
var number = 1000;

var data = {
    list: []
};
for (var i = 0; i < length; i ++) {
    data.list.push({
        index: i,
        user: '<strong>繁星</strong>',
        site: 'http://fanxing.kugou.com/'
    }); 
};
//Fxtpl分隔符改为“{{}}”格式
Fxtpl.config.leftTag = '{{';
Fxtpl.config.rightTag = '}}';
//测试器
var testList0 = [
    {
        name: 'Fxtpl 编译+渲染',
        tester: function () {
            var source = document.getElementById('fxtpl').innerHTML;
            for (var i = 0; i < number; i ++) {
                var fn = Fxtpl.compile(source);
                fn(data);
            }
        }
    },
    {
        name: 'artTemplate 编译+渲染',
        tester: function () {
            template.config('escape', false);
            var source = document.getElementById('template').innerHTML;
			for (var i = 0; i < number; i ++) {
                var fn = template.compile(source);
                fn(data);
            }
        }
    },
    {
        name: 'baiduTemplate 编译+渲染',
        tester: function () {
            var bt=baidu.template;
            var source = document.getElementById('baidu-template').innerHTML;
            bt.ESCAPE = false;
            for (var i = 0; i < number; i ++) {
               var fn = bt._compile(source);
               fn(data);
            }
        }
    },
    {
        name: 'tmpl 编译+渲染',
        tester: function () {
            var source = document.getElementById('tmpl').innerHTML;
            for (var i = 0; i < number; i ++) {
                var fn = tmpl(source);
                fn(data);
            }
        }
    },
    {
        name: 'juicer 编译+渲染',
        tester: function () {
            juicer.set('cache',false);

            var source = document.getElementById('juicer').innerHTML;
            for (var i = 0; i < number; i ++) {
                juicer(source, data);
            }
        }
    },
    {
        name: 'Mustache 编译+渲染',
        tester: function () {
            var source = document.getElementById('Mustache').innerHTML;
            for (var i = 0; i < number; i ++) {
                var fn = Mustache.compile(source, {cache: false});
                fn(data);
            }
        }
    },
    {
        name: 'kissy 编译+渲染',
        tester: function () {
            KISSY.use('template',function(S,T){
                console.time('kissy 编译+渲染');
                var source= document.getElementById('kissy').innerHTML;
                
                for (var i = 0; i < number; i ++) {
                    var fn = T(source).render;
                    fn(data);
                }
                console.timeEnd('kissy 编译+渲染');
            });
        }
    }
];
//编译 测试器
var testList1 = [
    {
        name: 'Fxtpl 编译',
        tester: function () {
            var source = document.getElementById('fxtpl').innerHTML;
            for (var i = 0; i < number; i ++) {
                var fn = Fxtpl.compile(source);
                //console.log(fn)
            }
        }
    },
    {
        name: 'artTemplate 编译',
        tester: function () {
            template.config('escape', false);
            var source = document.getElementById('template').innerHTML;
            for (var i = 0; i < number; i ++) {
                var fn = template.compile(source);
                //console.log(fn)
            }
        }
    },
    {
        name: 'baiduTemplate 编译',
        tester: function () {
            var bt=baidu.template;
            var source = document.getElementById('baidu-template').innerHTML;
            bt.ESCAPE = false;
            for (var i = 0; i < number; i ++) {
                var fn = bt._compile(source);
                //console.log(fn)
            }
        }
    },
    {
        name: 'tmpl 编译',
        tester: function () {
            var source = document.getElementById('tmpl').innerHTML;
            for (var i = 0; i < number; i ++) {
                var fn = tmpl(source);
                //console.log(fn)
            }
        }
    },
    {
        name: 'juicer 编译',
        tester: function () {
            juicer.set('cache',false);

            var source = document.getElementById('juicer').innerHTML;
            for (var i = 0; i < number; i ++) {
                var fn = juicer(source)._render;
                //console.log(fn)
            }
        }
    },
    {
        name: 'Mustache 编译',
        tester: function () {
            var source = document.getElementById('Mustache').innerHTML;
            for (var i = 0; i < number; i ++) {
                var fn = Mustache.compile(source, {cache: false});
            }
        }
    },
    {
        name: 'kissy 编译',
        tester: function () {
            KISSY.use('template',function(S,T){
                console.time('kissy 编译');
                var source= document.getElementById('kissy').innerHTML;
                
                for (var i = 0; i < number; i ++) {
                    var fn = T(source).render;
                    //console.log(fn)
                }
                console.timeEnd('kissy 编译');
            });
        }
    }
];
//渲染 测试器
var testList2 = [
    {
        name: 'Fxtpl 渲染',
        tester: function () {
            var source = document.getElementById('fxtpl').innerHTML;
            var fn = Fxtpl.compile(source);
            for (var i = 0; i < number; i ++) {
                fn(data);
            }
        }
    },
    {
        name: 'artTemplate 渲染',
        tester: function () {
            template.config('escape', false);
            var source = document.getElementById('template').innerHTML;
            var fn = template.compile(source);
            for (var i = 0; i < number; i ++) {
                fn(data);
            }
        }
    },
    {
        name: 'baiduTemplate 渲染',
        tester: function () {
            var bt=baidu.template;
            var source = document.getElementById('baidu-template').innerHTML;
            bt.ESCAPE = false;
            var fn = bt._compile(source);
            for (var i = 0; i < number; i ++) {
                fn(data);
            }
        }
    },
    {
        name: 'tmpl 渲染',
        tester: function () {
            var source = document.getElementById('tmpl').innerHTML;
            var fn = tmpl(source);
            for (var i = 0; i < number; i ++) {
                fn(data);
            }
        }
    },
    {
        name: 'juicer 渲染',
        tester: function () {
            juicer.set('cache',true);

            var source = document.getElementById('juicer').innerHTML;
            for (var i = 0; i < number; i ++) {
                juicer(source, data);
            }
        }
    },
    {
        name: 'Mustache 渲染',
        tester: function () {
            var source = document.getElementById('Mustache').innerHTML;
            var fn = Mustache.compile(source);
            for (var i = 0; i < number; i ++) {
                fn(data);
            }
        }
    },
    {
        name: 'kissy 渲染',
        tester: function () {
            KISSY.use('template',function(S,T){
                console.time('kissy 渲染');
                var source= document.getElementById('kissy').innerHTML;
                var fn = T(source).render;
                for (var i = 0; i < number; i ++) {
                    fn(data);
                }
                console.timeEnd('kissy 渲染');
            });
        }
    }
];
if(!window.console){
    window.console = {};
}
console.time = function(name){
    test_result[name] = new Date*1;
}
console.timeEnd = function(name){
    var endTime = (new Date*1 - test_result[name]);
    chart.series[0].addPoint({
        y: endTime
    });
}
function startTest(a, num){
    a.disabled = true;
    window.test_result = $('.test_log').eq(num);
    window.testList = window['testList' + num];
    test_result.innerHTML = '测试中...';
    highchartsLog.testType = testList[0].name.split(' ')[1];
    highchartsLog('chart_box' + num);
    tplTester(testList[0]);
}
function tplTester(ter){
    if(ter.name.indexOf('kissy')!==-1){
        ter.tester();
        return;
    }
    console.time(ter.name);
    ter.tester();
    console.timeEnd(ter.name);
    testList.shift();
    setTimeout(function(){
        testList[0] && tplTester(testList[0]);
    },500);
}
function highchartsLog(box){
    //var colors = Highcharts.getOptions().colors;
    var categories = [];

    for (var i = 0; i < testList.length; i ++) {
        categories.push(testList[i].name.split(' ')[0]);
    }

    window.chart = new Highcharts.Chart({
        chart: {
            renderTo: box,
            height: categories.length * 40,
            type: 'bar'
        },

        title: {
            text: 'JavaScript 模板引擎测试'
        },

        subtitle: {
            text: length + ' 条数据 × ' + number + ' 次' + highchartsLog.testType
        },
                
        xAxis: {
            categories: categories,
            labels: {
                align: 'right',
                style: {
                    fontSize: '12px',
                    fontFamily: 'Verdana, sans-serif'
                }
            }
        },

        yAxis: {
            min: 0,
            title: {
                text: '耗时(毫秒)'
            }
        },

        legend: {
            enabled: false
        },

        tooltip: {
            formatter: function() {
                return '<b>'+ this.x +'</b><br/>'+
                    this.y + '毫秒';
            }

        },

        credits: {
            enabled: false
        },
        plotOptions: {
            bar: {
                dataLabels: {
                    enabled: true,
                    formatter: function () {
                        return this.y + 'ms';
                    }
                }
            }
        },
        series: [{
            data : []
        }]

    });
}
</script>
</html>
